package com.aggregate.pay.yufu.cpos.support;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.aggregate.pay.yufu.cpos.bean.ResultReply;
import com.aggregate.pay.yufu.cpos.bean.ResultReplyReturnCode;
import com.aggregate.pay.yufu.cpos.enums.ReturnCode;
import com.aggregate.pay.yufu.cpos.support.utils.JSON;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tesla.tunguska.cuppay.util.CipherSignUtil;

/**
 * 接口API操作类抽象类
 * @author Moyq5
 * @date 2017年9月4日
 * @param <D>
 * @param <R>
 */
public abstract class AbstractClient<D, R extends ResultReply> implements Client<D, R> {

	private static Logger log = LoggerFactory.getLogger(AbstractClient.class);
	
	@Override
	public R execute(D data) {
		R result = null;
		try {
			HttpClient client = Factory.getHttpClient();
			String reqBody = getReqBody(data);
			String resBody = client.post(getServerPath(), reqBody);
			result = converToResult(resBody);
			/*
			if (resResult.getRespCode() == RespCode.SUCCESS) {
				String sign = Tool.sign(resBody, cfg.getKey());
				if (!sign.equals(resResult.getSign())) {
					throw new Exception("签名验证失败");
				} else {
					log.debug("签名验证通过");
				}
			}*/
		} catch (Exception e) {
			log.error("接口调用失败", e);
			ResultReplyReturnCode returnCode = new ResultReplyReturnCode();
			ReturnCode code = ReturnCode.FAIL;
			code.setText("9999");
			returnCode.setCode(code);
			returnCode.setMessage(e.getMessage());
			returnCode.setType("E");
			result = JSON.toObject("{}", getResultClass());
			result.setReturnCode(returnCode);
		}
		return result;
	}

	private R converToResult(String resBody) throws IOException, JsonProcessingException {
		ObjectMapper mapper = new ObjectMapper();
		JsonNode actualObj = mapper.readTree(resBody);
		actualObj = actualObj.get("reply");
		return JSON.toObject(actualObj.toString(), getResultClass());
	}
	
	private String getReqBody(D data) throws Exception {
		Map<String, Object> params = convertToMap(data);
		//安全校验参数
        String timestamp = String.valueOf(System.currentTimeMillis()+1*60*1000);
        params.put("timestamp", timestamp);
		
        Config cfg = Factory.getConfig();
		InputStream keyInputStream = new FileInputStream(new File(cfg.getPrivateKeyPath()));
		String encryptedSign = CipherSignUtil.paramSignAndEncryptBase64String(params, cfg.getPrivateKeyPwd(), cfg.getPrivateKeyAlias(), keyInputStream);
		String summaryPlain = CipherSignUtil.paramMap2SHA1Base64String(params);
		
		params.put("thdSysNme", cfg.getThirdSysName());
		params.put("timestamp", timestamp);
		params.put("encryptedSign", encryptedSign);
		params.put("summaryPlain", summaryPlain);
		
		return JSON.toString(params);
	}
	
	protected abstract Map<String, Object> convertToMap(D data);

	protected abstract String getServerPath();
	
	protected abstract Class<R> getResultClass();
}
